<?php

class Jf_Tree_Href_Mvc extends Jf_Tree_Node {

    protected $_action;

    protected $_controller;

    protected $_module;

    protected $_params = array();

    protected $_route;

    protected $_resetParams = true;

    protected $_encodeUrl = true;

    protected $_active = null;

    protected $_scheme;

    protected $_hrefCache;

    protected static $_urlHelper = null;

    protected static $_schemeHelper = null;

    public function isActive ($recursive = false) {
        if (null === $this -> _active) {
            $dispatcher = Jf_Controller_Dispatcher::getInstance ();
            $request = $dispatcher -> getRequest ();
            $reqParams = array();
            if ($request) {
                $reqParams = $request -> getParams ();
                if ( ! array_key_exists ('module', $reqParams)) {
                    $reqParams['module'] = $dispatcher -> getDefaultModule ();
                }
            }
            $reqParams['module'] = strtolower ($dispatcher -> getRequest () -> getModuleName ());
            $reqParams['controller'] = strtolower ($dispatcher -> getRequest () -> getControllerName ());
            $reqParams['action'] = $dispatcher -> getRequest () -> getActionName ();
            $myParams = $this -> _params;
            if ($this -> _route) {
                $route = $dispatcher -> getRouter () -> getRoute ($this -> _route);
                if (method_exists ($route, 'getDefaults')) {
                    $myParams = array_merge ($route -> getDefaults (), $myParams);
                }
            }
            if (null !== $this -> _module) {
                $myParams['module'] = $this -> _module;
            } elseif ( ! array_key_exists ('module', $myParams)) {
                $myParams['module'] = $dispatcher -> getDefaultModule ();
            }
            if (null !== $this -> _controller) {
                $myParams['controller'] = $this -> _controller;
            } elseif ( ! array_key_exists ('controller', $myParams)) {
                $myParams['controller'] = $dispatcher -> getDefaultController ();
            }
            if (null !== $this -> _action) {
                $myParams['action'] = $this -> _action;
            } elseif ( ! array_key_exists ('action', $myParams)) {
                $myParams['action'] = $dispatcher -> getDefaultAction ();
            }
            foreach ($myParams as $key => $value) {
                if ($value == null) {
                    unset ($myParams[$key]);
                }
            }
            if (count (array_intersect_assoc ($reqParams, $myParams)) == count ($myParams)) {
                $this -> _active = true;
                return true;
            }
            $this -> _active = false;
        }
        return parent::isActive ($recursive);
    }

    /**
     * Returns href for this page
     * This method uses {@link Zend_Controller_Action_Helper_Url} to assemble
     * the href based on the page's properties.
     * @return string page href
     */
    public function getHref () {
        if ($this -> _hrefCache) {
            return $this -> _hrefCache;
        }
        /*
         * if (null === self::$_urlHelper) { self::$_urlHelper = Zend_Controller_Action_HelperBroker::getStaticHelper('Url'); } $params = $this->getParams(); if ($param = $this->getModule()) { $params['module'] = $param; } if ($param = $this->getController()) { $params['controller'] = $param; } if ($param = $this->getAction()) { $params['action'] = $param; } $url = self::$_urlHelper->url($params, $this->getRoute(), $this->getResetParams(), $this->getEncodeUrl());
         */
        $url = '/' . $this -> getModule () . '/';
        $url .= $this -> getController () . '/';
        $url .= $this -> getAction ();
        // Use scheme?
        $scheme = $this -> getScheme ();
        if (null !== $scheme) {
            if (null === self::$_schemeHelper) {
                self::$_schemeHelper = new Jf_View_Helper_ServerUrl ();
            }
            $url = self::$_schemeHelper -> setScheme ($scheme) -> serverUrl ($url);
        }
        // Add the fragment identifier if it is set
        $fragment = $this -> getFragment ();
        if (null !== $fragment) {
            $url .= '#' . $fragment;
        }
        return $this -> _hrefCache = $url;
    }

    /**
     * Sets action name to use when assembling URL
     * @see getHref()
     *
     * @param string $action action name
     * @return Jf_Tree_Node_Mvc fluent interface, returns self
     * @throws Jf_Tree_Exception if invalid $action is given
     */
    public function setAction ($action) {
        if (null !== $action &&  ! is_string ($action)) {
            require_once 'Jf/Tree/Exception.php';
            throw new Jf_Tree_Exception ('Invalid argument: $action must be a string or null');
        }
        $this -> _action = $action;
        $this -> _hrefCache = null;
        return $this;
    }

    /**
     * Returns action name to use when assembling URL
     * @see getHref()
     *
     * @return string null name
     */
    public function getAction () {
        return $this -> _action;
    }

    /**
     * Sets controller name to use when assembling URL
     * @see getHref()
     *
     * @param string|null $controller controller name
     * @return Jf_Tree_Node_Mvc fluent interface, returns self
     * @throws Jf_Tree_Exception if invalid controller name is given
     */
    public function setController ($controller) {
        if (null !== $controller &&  ! is_string ($controller)) {
            require_once 'Jf/Tree/Exception.php';
            throw new Jf_Tree_Exception ('Invalid argument: $controller must be a string or null');
        }
        $this -> _controller = $controller;
        $this -> _hrefCache = null;
        return $this;
    }

    /**
     * Returns controller name to use when assembling URL
     * @see getHref()
     *
     * @return string null name or null
     */
    public function getController () {
        return $this -> _controller;
    }

    /**
     * Sets module name to use when assembling URL
     * @see getHref()
     *
     * @param string|null $module module name
     * @return Jf_Tree_Node_Mvc fluent interface, returns self
     * @throws Jf_Tree_Exception if invalid module name is given
     */
    public function setModule ($module) {
        if (null !== $module &&  ! is_string ($module)) {
            require_once 'Jf/Tree/Exception.php';
            throw new Jf_Tree_Exception ('Invalid argument: $module must be a string or null');
        }
        $this -> _module = $module;
        $this -> _hrefCache = null;
        return $this;
    }

    /**
     * Returns module name to use when assembling URL
     * @see getHref()
     *
     * @return string null name or null
     */
    public function getModule () {
        return $this -> _module;
    }

    /**
     * Set multiple parameters (to use when assembling URL) at once
     * URL options passed to the url action helper for assembling URLs.
     * Overwrites any previously set parameters!
     * @see getHref()
     *
     * @param array|null $params [optional] paramters as array
     *        ('name' => 'value'). Default is null
     *        which clears all params.
     * @return Jf_Tree_Node_Mvc fluent interface, returns self
     */
    public function setParams (array $params = null) {
        $this -> clearParams ();
        if (is_array ($params)) {
            $this -> addParams ($params);
        }
        return $this;
    }

    /**
     * Set parameter (to use when assembling URL)
     * URL option passed to the url action helper for assembling URLs.
     * @see getHref()
     *
     * @param string $name parameter name
     * @param mixed $value parameter value
     * @return Jf_Tree_Node_Mvc fluent interface, returns self
     */
    public function setParam ($name, $value) {
        $name = (string) $name;
        $this -> _params[$name] = $value;
        $this -> _hrefCache = null;
        return $this;
    }

    public function addParams (array $params) {
        foreach ($params as $name => $value) {
            $this -> setParam ($name, $value);
        }
        return $this;
    }

    public function removeParam ($name) {
        if (array_key_exists ($name, $this -> _params)) {
            unset ($this -> _params[$name]);
            $this -> _hrefCache = null;
            return true;
        }
        return false;
    }

    public function clearParams () {
        $this -> _params = array();
        $this -> _hrefCache = null;
        return $this;
    }

    public function getParams () {
        return $this -> _params;
    }

    public function getParam ($name) {
        $name = (string) $name;
        if ( ! array_key_exists ($name, $this -> _params)) {
            return null;
        }
        return $this -> _params[$name];
    }

    public function setRoute ($route) {
        if (null !== $route && ( ! is_string ($route) || strlen ($route) < 1)) {
            throw new Jf_Tree_Exception ('Invalid argument: $route must be a non-empty string or null');
        }
        $this -> _route = $route;
        $this -> _hrefCache = null;
        return $this;
    }

    public function getRoute () {
        return $this -> _route;
    }

    public function setResetParams ($resetParams) {
        $this -> _resetParams = (bool) $resetParams;
        $this -> _hrefCache = null;
        return $this;
    }

    public function getResetParams () {
        return $this -> _resetParams;
    }

    public function setEncodeUrl ($encodeUrl) {
        $this -> _encodeUrl = (bool) $encodeUrl;
        $this -> _hrefCache = null;
        return $this;
    }

    public function getEncodeUrl () {
        return $this -> _encodeUrl;
    }

    public function setScheme ($scheme) {
        if (null !== $scheme &&  ! is_string ($scheme)) {
            throw new Jf_Tree_Exception ('Invalid argument: $scheme must be a string or null');
        }
        $this -> _scheme = $scheme;
        return $this;
    }

    public function getScheme () {
        return $this -> _scheme;
    }

    public static function setUrlHelper (Zend_Controller_Action_Helper_Url $uh) {
        self::$_urlHelper = $uh;
    }

    public static function setSchemeHelper (Zend_View_Helper_ServerUrl $sh) {
        self::$_schemeHelper = $sh;
    }

    public function toArray () {
        return array_merge (parent::toArray (), array('action' => $this -> getAction (), 'controller' => $this -> getController (), 'module' => $this -> getModule (), 'params' => $this -> getParams (), 'route' => $this -> getRoute (), 'reset_params' => $this -> getResetParams (), 'encodeUrl' => $this -> getEncodeUrl (), 'scheme' => $this -> getScheme ()));
    }

}
